<?php

class DomainMapper
{

  /**
   *
   * @param IDomObjDefinition $definition
   * @param array $data
   * @return array
   */
  public static function inflateCollection(IDomObjDefinition $definition, $data, $depth = -1)
  {
    if (! empty($data)) {
      foreach ($data as &$row) {
        $row = DomainMapper::inflateObj($definition, $row, $depth - 1);
      }
    }

    return $data;
  }

  /**
   *
   * @param IDomObjDefinition $definition
   * @param array $data
   * @return IDomObj
   */
  public static function inflateObj(IDomObjDefinition $definition, $data, $depth = -1)
  {
    $def = Domain::toEntity($definition);

    $name = $def->getClass();
    $id = $data[$def->getPk()];

    if (DomainRegistry::has($name, $id)) {
      return DomainRegistry::get($name, $id);
    }

    $obj = $definition->factory();

    try {
      $def = Domain::toEntity($definition);

      foreach ($definition->getFields() as $name => $field) {
        $field = $def->getField($name);

        if (isset($data[$field->getName()])) {
          $obj->$name = $data[$field->getName()];

          //unset($data[$field->getName()]);
        }
      }
    }
    catch (DomainTypeConversionException $e) {
      // obj is not an entity
    }

    if ($depth != 0) {
      try {
        $def = Domain::toAggregate($definition);

        foreach ($def->getAssociations() as $name => $assoc) {
          $assoc = $def->getAssociation($name);

          if (isset($data[$name])) {
            if ($assoc->isSingle()) {
              $obj->$name = DomainMapper::inflateObj($assoc->getTarget(), $data[$name], $depth - 1);
            }
            else {
              $obj->$name = DomainMapper::inflateCollection($assoc->getTarget(), $data[$name], $depth - 1);
            }

            //unset($data[$name]);
          }
        }
      }
      catch (DomainTypeConversionException $e) {
        // obj is not an aggregate
      }
    }

    $obj->copyAll($data);
    $obj->commit();

    DomainRegistry::set($obj);

    return $obj;
  }

}

?>